//package main;
//
//import bots.*;
//import model.GameType;
//import model.Player;
//import org.apache.log4j.Logger;
//import org.encog.ml.MLRegression;
//import org.encog.ml.genetic.genome.Genome;
//import org.encog.ml.genetic.population.Population;
//import org.encog.neural.neat.training.NEATTraining;
//import org.encog.neural.networks.training.CalculateScore;
//import util.Util;
//
//import java.util.List;
//import java.util.concurrent.ForkJoinPool;
//
///**
// * @author Alex Vikharev vikharev@yandex-team.ru
// *         created 12.02.12
// */
//public class CrossTraining {
//    private static final Logger log = Logger.getLogger(CrossTraining.class);
//
//    public static void main(String[] args) {
//        ForkJoinPool pool = new ForkJoinPool();
//        Player bot = new LightLookAheadBot(GameType.IMPROVED, "Name", 1, pool);
//
//        NEATEvaluator evaluator = new NEATEvaluator(bot);
//        NEATTraining training = new NEATTraining(evaluator, 17 * 5, 1, 100);
//
//        training.setParamMaxPermittedNeurons(500);
//        evaluator.setTraining(training);
//
//        for (int i = 0; i < 100000; i++) {
//            log.info("Epoch: " + i);
//            training.iteration();
//            if (i % 10 == 0) {
//                MLRegression best = (MLRegression) training.getMethod();
//                log.info("Best score: " + training.getPopulation().getBest().getScore());
//                testAndSaveBest(best, i);
//            }
//        }
//    }
//
//    private static void testAndSaveBest(MLRegression classifier, int epoch) {
//        Player bot = new MinMaxMLClassifierBot("Classifier bot", classifier);
//        Player random = new RandomBot("Random bot");
//        testPlay(bot, random);
//
//        String fileName = String.format("cross-trained-epoch%d.classifier", epoch);
//        log.info("Serializing classifier into file: " + fileName);
//        Util.saveClassifier(classifier, fileName);
//    }
//
//    private static class NEATEvaluator implements CalculateScore {
//        private final Player bot;
//        private NEATTraining training;
//
//        private NEATEvaluator(Player bot) {
//            this.bot = bot;
//        }
//
//        public void setTraining(NEATTraining training) {
//            this.training = training;
//        }
//
//        private double calculateScoreWithBot(Player bot) {
//            double result = 0.0;
//            for (int i = 0; i < 50; i++) {
//                Game game = new Game(bot, this.bot, GameType.IMPROVED);
//                game.go();
//                switch (game.getState()) {
//                    case FIRST_PLAYER_WIN:
//                        result += 10;
//                        break;
//                    case TIE:
//                        result += 1;
//                }
//            }
//            return result;
//        }
//
//        @Override
//        public double calculateScore(MLRegression mlRegression) {
//            MLClassifierBot one = new MinMaxMLClassifierBot("First", mlRegression);
//            if (training == null) {
//                return calculateScoreWithBot(one);
//            }
//            Population population = training.getPopulation();
//            List<Genome> genomes = population.getGenomes();
//            double result = 0;
//            for (Genome genome : genomes) {
//                genome.decode();
//                MLRegression organism = (MLRegression) genome.getOrganism();
//                if (organism == mlRegression) {
//                    continue;
//                }
//                MLClassifierBot two = new MinMaxMLClassifierBot("Second", organism);
//
//                Game game = new Game(one, two, GameType.IMPROVED);
//                game.go();
//                switch (game.getState()) {
//                    case FIRST_PLAYER_WIN:
//                        result += 10;
//                        break;
//                    case TIE:
//                        result += 1;
//                }
//            }
//            return result;
//        }
//
//        @Override
//        public boolean shouldMinimize() {
//            return false;
//        }
//    }
//
//    private static void testPlay(Player bot1, Player bot2) {
//        int firstWin = 0;
//        int secondWin = 0;
//        int tie = 0;
//
//        log.info("Start testing games");
//        int runs = 100;
//        for (int t = 0; t < runs; t++) {
//            log.debug("Test game " + t);
//
//            Game game = new Game(bot1, bot2, GameType.IMPROVED);
//
//            game.go();
//            switch (game.getState()) {
//                case FIRST_PLAYER_WIN:
//                    firstWin++;
//                    break;
//                case SECOND_PLAYER_WIN:
//                    secondWin++;
//                    break;
//                default:
//                    tie++;
//            }
//            log.debug(game.getState());
//        }
//        log.info(String.format("First player (%s) wins: %d Second player (%s) wins: %d Ties: %d", bot1.toString(), firstWin, bot2.toString(), secondWin, tie));
//    }
//}
